package zack.project.domain.strategy.service.raffle;

import zack.project.domain.strategy.adapter.repository.IStrategyRepository;
import zack.project.domain.strategy.model.entity.StrategyAwardEntity;
import zack.project.domain.strategy.model.valobj.RuleTreeVO;
import zack.project.domain.strategy.model.valobj.RuleWeightVO;
import zack.project.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import zack.project.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import zack.project.domain.strategy.service.AbstractRaffleStrategy;
import zack.project.domain.strategy.service.IRaffleAward;
import zack.project.domain.strategy.service.IRaffleRule;
import zack.project.domain.strategy.service.IRaffleStock;
import zack.project.domain.strategy.service.armory.IStrategyDispatch;
import zack.project.domain.strategy.service.rule.chain.ILogicChain;
import zack.project.domain.strategy.service.rule.chain.factory.DefaultChainFactory;
import zack.project.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import zack.project.domain.strategy.service.rule.tree.factory.engine.impl.DecisionTreeEngine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**1.抽奖策略的默认实现,实现抽象类定义的责任链和决策树
 * 2.实现IRaffleAward:查询奖品列表
 * 3.实现IRaffleStock:获取延迟消息更新数据库表
 * 4.
 * @author A1793
 */
@Service
@Slf4j
public class DefaultRaffleStrategy extends AbstractRaffleStrategy implements IRaffleAward,
        IRaffleStock,
        IRaffleRule {


    public DefaultRaffleStrategy(DefaultChainFactory logicChainFactory,
                                 DefaultTreeFactory logicTreeFactory,
                                 IStrategyRepository repository,
                                 IStrategyDispatch strategyDispatch) {
        super(logicChainFactory, logicTreeFactory, repository, strategyDispatch);
    }

    /**
     * 通过责任链工厂开启责任链流转
     * @param userId
     * @param strategyId
     * @return
     */
    @Override
    public DefaultChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId) {
        log.info("抽奖策略-责任链 userId:{} strategyId:{}", userId, strategyId);
        //开启责任链，用strategyId去查数据库表{strategy}，根据strategy配置rule_models构建对应的责任链节点并组装
        ILogicChain iLogicChain = this.logicChainFactory.openLogicChain(strategyId);
        return iLogicChain.logic(userId, strategyId);
    }

    @Override
    public DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId,
                                                              Long strategyId,
                                                              Integer awardId) {
        return raffleLogicTree(userId, strategyId, awardId, null);
    }

    /**
     * 决策树流程,根据决策树工厂启动决策引擎进行决策流转
     * @param userId
     * @param strategyId
     * @param awardId
     * @param endDateTime
     * @return
     */
    @Override
    public DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId,
                                                              Long strategyId,
                                                              Integer awardId,
                                                              Date endDateTime) {
        // 根据策略id和奖品去查询{strategy_award}中对应奖品的rule_models(实际就是该奖品要走的规则树的树id)
        StrategyAwardRuleModelVO strategyAwardRuleModelVO = this.repository.
                queryStrategyAwardRuleModelVO(strategyId, awardId);

        if (strategyAwardRuleModelVO == null) {
            return DefaultTreeFactory.StrategyAwardVO.builder().build();
        }
        log.info("抽奖策略-规则树 userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);
        //这个ruleModel就是该奖品要走的规则树的树id，
        // 根据树id去查询rule_tree,rule_tree_node,rule_tree_node_line，构建规则树
        RuleTreeVO ruleTreeVO =
                repository.queryRuleTreeVOByTreeId(strategyAwardRuleModelVO.getRuleModel());

        if (ruleTreeVO == null) {
            throw new RuntimeException("存在抽奖策略配置的规则模型 Key，未在库表 rule_tree、rule_tree_node、rule_tree_line 配置对应的规则树信息 " + strategyAwardRuleModelVO.getRuleModel());

        }
        DecisionTreeEngine decisionTreeEngine = this.logicTreeFactory.openLogicTreeNode(ruleTreeVO);
        return decisionTreeEngine.process(userId, strategyId, awardId, endDateTime);

    }

    /**
     * IRaffleStock接口方法
     * 从redis阻塞队列获取StrategyAwardStockKeyVO消息
     * @return
     */
    @Override
    public StrategyAwardStockKeyVO takeQueueValue() {
        return repository.takeQueueValue();
    }

    /**
     * 根据从延迟队列获得消息更新数据库表{strategy_award}
     * @param strategyId
     * @param awardId
     */
    @Override
    public void updateStrategyAwardStock(Long strategyId, Integer awardId) {
        repository.updateStrategyAwardStock(strategyId, awardId);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardList(Long strategyId) {
        return repository.queryStrategyAwardList(strategyId);
    }

    @Override
    public List<StrategyAwardEntity> queryRaffleStrategyAwardListByActivityId(Long activityId) {
        Long strategyId = repository.queryStrategyIdByActivityId(activityId);
        return repository.queryStrategyAwardList(strategyId);

    }

    @Override
    public Map<String, Integer> queryAwardRuleLockCount(String[] treeIds) {
        return repository.queryAwardRuleLockCount(treeIds);
    }

    @Override
    public List<RuleWeightVO> queryAwardRuleWeightByActivityId(Long activityId) {
        Long strategyId = repository.queryStrategyIdByActivityId(activityId);
        return queryAwardRuleWeight(strategyId);

    }

    @Override
    public List<RuleWeightVO> queryAwardRuleWeight(Long strategyId) {
        return repository.queryAwardRuleWeight(strategyId);
    }
}

